/**
 * @Author: wzx
 * @Description:
 * @Version: 1.0.0
 * @Date: 2021/5/17 下午6:56
 *@Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
 */

package router

import (
	"context"
	"fmt"
	"math/rand"
	"runtime/debug"
	"time"
	"vpn-management-server/logger"
	"vpn-management-server/network"
	"vpn-management-server/security/code"
	km "vpn-management-server/security/keymanager"
)

func StartSecRouter(address string, sslAdress string, key *km.KeyManager) {
	if key.IsOnCurve() == false {
		logger.Logger.Fatal("Server creates failed..., because the private key and public key don't match.")
	}

	net := network.TCPNet{}
	// 加密连接监听
	err := net.Listens(address, sslAdress, key)
	if err != nil {
		logger.Logger.Fatal("Server Listens failed...")
	}
	start(&net)
}

func start(net network.Net) {
	logger.Logger.Info("The server start success....")
	for {
		// accept连接
		conn, err := net.Accept()
		if err != nil {
			logger.Logger.Fatal("Error accepting", err.Error())
		}
		// 开启一个新协程 单独处理连接
		go handle(conn)
		// 开启一个协程 单独处理过期密钥和过期的sessionID
	}
}

func handle(conn network.Connect) {
	// 随机生成一个10位的数字 作为连接ID 生成context字节点 并存储数值key:value
	connID := fmt.Sprintf("%09v", rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(1e10))
	ctx := context.WithValue(context.Background(), "conn_id", connID)

	defer func() {
		if err := recover(); err != nil {
			logger.Logger.Error("panic when program execute,err:", err)
			debug.PrintStack()
		}
		if err := conn.Close(); err != nil {
			logger.Logger.Error("handle conn fail,err:", err)
		}
	}()

	for {
		var resp = network.NewNetResponse()
		var req = network.NewNetRequest()
		// 读取buf数据
		buf, err := conn.Read()
		if err != nil {
			logger.Logger.ErrorWithIdAndConn(connID, conn.GetRemote(), "read msg fail,err:", err)
			resp.Code = code.UNAUTHORIZED
			resp.ErrorMsg = err.Error()
			goto LABLE
		}
		// 设置conn
		resp.SetConnect(conn)
		logger.Logger.DebugfWithIdAndConn(ctx.Value("conn_id").(string), conn.GetRemote(), "The Server Received data: %v", string(buf))
		// 读取buf解析成结构体 赋值给req
		err = req.SetJsonInfo(buf)
		if err != nil {
			logger.Logger.ErrorfWithIdAndConn(ctx.Value("conn_id").(string), conn.GetRemote(), "Error Unmarshal Json Message, "+string(buf))
			resp.Code = code.BAD_REQUEST
			resp.ErrorMsg = "Error Unmarshal Json Message"
			goto LABLE
		}
		logger.Logger.Debug("parameters:", string(req.Parameters))
		// 设置连接
		req.SetConnection(conn)

		if req.Type == "" {
			logger.Logger.ErrorfWithIdAndConn(ctx.Value("conn_id").(string), conn.GetRemote(), "Error the Request Type is Null, "+string(buf))
			resp.Code = code.BAD_REQUEST
			resp.ErrorMsg = "Error the Request Type is Null"
		} else {
			// 跟据Type 取出对应的 router
			if f, ok := gRouters.typeRouters[req.Type]; !ok {
				logger.Logger.ErrorfWithIdAndConn(ctx.Value("conn_id").(string), conn.GetRemote(), "Not Supported the Request Type, "+string(buf))
				resp.Code = code.BAD_REQUEST
				resp.ErrorMsg = "Not Supported the Request Type"
			} else {
				isCon := true
				if bf, ok := gRouters.beforeRouter[req.Type]; bf != nil && ok {
					isCon = bf(ctx, req, resp)
				} else {
					logger.Logger.Warn("beforeRouter is not registered")
				}

				if isCon == true {
					f(ctx, req, resp)
					if af, ok := gRouters.afterRouter[req.Type]; af != nil && ok {
						af(ctx, req, resp)
					}
				} else {
					logger.Logger.Warn("beforeRouter validate fail")
				}
			}
		}
	LABLE:
		// 从response中取出回复json
		respData := resp.GetJsonInfo()
		// 写入 发送给客户端
		err = conn.Write(respData)
		if err != nil {
			logger.Logger.ErrorfWithIdAndConn(ctx.Value("conn_id").(string), conn.GetRemote(), "Error Send Json Message, "+string(respData))
		}

		switch req.Header["Mode"] {
		case network.ShortConn:
			return
		case network.LongConn:
			continue
		default:
			return
		}

	}
}
